package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.constant.AuthContent;
import com.hbx.constant.RspEnum;
import com.hbx.constant.TableEnum;
import com.hbx.logs.annotation.MarkLog;
import com.hbx.logs.OperaTypeEnum;
import com.hbx.dto.role.InsertOrUpdateRoleDto;
import com.hbx.dto.role.SaveMenuDto;
import com.hbx.exception.RspException;
import com.hbx.mapper.MenuMapper;
import com.hbx.mapper.RoleMenuMapper;
import com.hbx.mapper.RoleUserMapper;
import com.hbx.model.Menu;
import com.hbx.model.Role;
import com.hbx.mapper.RoleMapper;
import com.hbx.model.RoleMenu;
import com.hbx.model.RoleUser;
import com.hbx.model.User;
import com.hbx.service.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.utils.Result;
import com.hbx.vo.PageBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hbx
 * @since 2021-11-26
 */
@Service
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    protected RoleUserMapper roleUserMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private MenuMapper menuMapper;

    /**
     * 分页获取角色
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Result getRoleList(Integer pageNum, Integer pageSize) {
        Result r = new Result();
        PageBean pageBean = new PageBean();
        Page<Role> page = new Page<>(pageNum,pageSize);
        IPage<Role> roleIPage = roleMapper.selectPage(page, null);
        pageBean.setTotal(roleIPage.getTotal());
        pageBean.setPageSize(roleIPage.getSize());
        pageBean.setPageNum(roleIPage.getCurrent());
        pageBean.setData(roleIPage.getRecords());
        return r.setCode(200).setData(pageBean).setMsg("success");
    }

    /**
     * 添加或修改角色
     * @param dto
     * @param r
     */
    @Override
    @Transactional
    public void insertOrUpdateRole(InsertOrUpdateRoleDto dto, Result r) {
        Integer roleId = dto.getRoleId();
        if (roleId != null){
            Role role = new Role();
            BeanUtils.copyProperties(dto,role);
            Integer update = roleMapper.updateById(role);
            if (update != null && update > 0){
                r.setCode(200).setMsg("角色修改成功");
            } else {
                r.setCode(201).setMsg("角色修改失败");
            }
        }else {
            Role role = new Role();
            BeanUtils.copyProperties(dto,role);
            Integer insert = roleMapper.insert(role);
            if (insert != null && insert > 0){
                // 查询基本菜单
                QueryWrapper<Menu> wrapper = new QueryWrapper<>();
                wrapper.eq("is_user",1);
                List<Menu> menuList = menuMapper.selectList(wrapper);
                if (menuList != null && menuList.size() > 0){
                    List<RoleMenu> list = new ArrayList<>();
                    menuList.stream().forEach(m -> {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRid(role.getRoleId());
                        roleMenu.setMid(m.getId());
                        list.add(roleMenu);
                    });
                    int i = roleMenuMapper.insertBatchs(list);
                    if (i > 0){
                        r.setCode(200).setMsg("角色添加成功");
                    } else{
                        throw new RspException("角色添加失败");
                    }
                }
                r.setCode(200).setMsg("角色添加成功");
            } else {
                r.setCode(201).setMsg("角色添加失败");
            }
        }
    }

    /**
     * 删除角色
     * @param roleId
     * @param r
     */
    @Override
    @Transactional
    public void deleteRole(Integer roleId, Result r) {
        QueryWrapper<RoleUser> wrapper = new QueryWrapper<>();
        wrapper.eq("rid",roleId);
        List<RoleUser> roleUsers = roleUserMapper.selectList(wrapper);
        if (roleUsers.size() == 0){
            int i = roleMapper.deleteById(roleId);
            if (i > 0){
                r.setCode(200).setMsg("角色删除成功");
                return;
            } else{
                throw new RspException(201,"角色删除失败");
            }
        }
        // 先删除权限，在删除角色
        int delete = roleUserMapper.delete(wrapper);
        if (delete > 0){
            int i = roleMapper.deleteById(roleId);
            if (i > 0){
                r.setCode(200).setMsg("角色删除成功");
            } else{
                throw new RspException(201,"角色删除失败");
            }
        }
    }

    /**
     * 根据角色id查菜单id
     * @param r
     */
    @Override
    public void getMenuIdByRoleId(Integer roleId, Result r) {
        QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("rid",roleId);
        List<RoleMenu> menuList = roleMenuMapper.selectList(wrapper);
        List<String> ids = menuList.stream()
                .map(RoleMenu::getMid)
                .map(a -> a + "")
                .collect(Collectors.toList());
        r.setCode(200).setData(ids);
    }

    /**
     * 给角色授权
     * @param dto
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.UPDATE,tables = TableEnum.SYS_ROLE_MENU,desc = "管理员给角色授权")
    public void savaMenuToRole(SaveMenuDto dto, Result r) {
        List<String> ids = dto.getIds();
        if (ids == null || ids.size() < 0){
            throw new RspException(201,"授权失败");
        }
        List<RoleMenu> list = new ArrayList<>();
        // 删除权限
         QueryWrapper<RoleMenu> wrapper = new QueryWrapper<>();
         wrapper.eq("rid",dto.getRoleId());
        List<RoleMenu> roleMenuList = roleMenuMapper.selectList(wrapper);
        if (roleMenuList.size() > 0){
            int delete = roleMenuMapper.delete(wrapper);
            if (delete > 0){
                // 重新授权
                if (ids.size() == 0){
                    r.setCode(200).setMsg("权限收回成功");
                    return;
                }
                ids.stream().forEach(str -> {
                    RoleMenu menu = new RoleMenu();
                    menu.setRid(dto.getRoleId());
                    menu.setMid(Integer.parseInt(str));
                    list.add(menu);
                });

                int result = roleMenuMapper.insertBatchs(list);
                if (result > 0){
                    r.setCode(200).setMsg("授权成功");
                }else{
                    r.setCode(201).setMsg("授权失败");
                }
            }
        } else {
            ids.stream().forEach(str -> {
                RoleMenu menu = new RoleMenu();
                menu.setRid(dto.getRoleId());
                menu.setMid(Integer.parseInt(str));
                list.add(menu);
            });

            int result = roleMenuMapper.insertBatchs(list);
            if (result > 0){
                r.setCode(200).setMsg("授权成功");
            }else{
                r.setCode(201).setMsg("授权失败");
            }
        }
    }

    /**
     * 获取所有可用角色
     * @param r
     */
    @Override
    public void getRoleAvaiList(Result r) {
        User user = AuthCacheService.getUser();
        if (ObjectUtils.isEmpty(user)) {
            throw new RspException(RspEnum.AUTH_NO_LOGIN);
        }
        List<Integer> rids = new ArrayList<>();
        if (!AuthContent.SUPER_ADMIN_CODE.equals(user.getType())) {
            QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("uid", user.getUserId());
            List<RoleUser> roleUsers = roleUserMapper.selectList(queryWrapper);
            if (CollectionUtils.isEmpty(roleUsers)){
                r.setCode(200).setData(new ArrayList<>(0));
                return;
            }
            rids = roleUsers.stream()
                    .map(RoleUser::getRid)
                    .distinct()
                    .collect(Collectors.toList());
            if (!rids.contains(AuthContent.COMMON_ROLE_ID)) {
                rids.add(AuthContent.COMMON_ROLE_ID);
            }
        } else {
            rids = roleMapper.selectList(null).stream().map(Role::getRoleId).collect(Collectors.toList());
        }
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.eq("available",1);
        wrapper.in("role_id", rids);
        List<Role> roleList = roleMapper.selectList(wrapper);
        r.setCode(200).setData(roleList);
    }
}
